import os.path
import sys
import types
from Xlib import X,XK
import operator

#THESE MASKS ARE GOING TO CONTROL HOW YOUR KEYBOARD MAPS TO THE MODIFIERS SPECIFIED
#IN THE USER CONFIG
_modmasks = {
    "shift":    X.ShiftMask,
    "lock":     X.LockMask,
    "control":  X.ControlMask,
    "mod1":     X.Mod1Mask,
    "mod2":     X.Mod2Mask,
    "mod3":     X.Mod3Mask,
    "mod4":     X.Mod4Mask,
    "mod5":     X.Mod5Mask,
    "alt":      X.Mod1Mask,
    "meta":     X.Mod4Mask,
    "win":      X.Mod4Mask,
    "ctrl":     X.ControlMask,
}


def translateMasks(modifiers):
    
    """
        Translate a modifier mask specified as a list of strings into an or-ed 
        bit representation.
    """
    masks = []
    for i in modifiers:
        try:
            masks.append(_modmasks[i])
        except KeyError:
            pass
    return reduce(operator.or_, masks) if masks else 0





class KeyConfig():
    @staticmethod
    def GetKeyBindings():
        ConfigError=False
        fname = os.path.join("~", ".glassbead", "keys.py")
        fname = os.path.expanduser(fname)
        if os.path.exists(fname):    
            try:
                globs={}
                execfile(fname, {}, globs)
            except Exception, v:
                ConfigError=True
        else:
            ConfigError=True
            
        if not ConfigError:
            namespaceexitbinding=['','']
            vnamespaceexitbinding=globs.get("EXITNAMESPACEKEY")
           
            if not vnamespaceexitbinding:
                namespaceexitbinding=[XK.string_to_keysym('Escape'),translateMasks("")]
            else:
                namespaceexitbinding[1]=translateMasks(str.lower(vnamespaceexitbinding[1]).split('+'))
                namespaceexitbinding[0] = XK.string_to_keysym(vnamespaceexitbinding[0])
                

            namespacebindings=globs.get("NAMESPACEBINDINGS")
            namespacebindinglist=[]
            keybindinglist=[]
           
            for namespacespec in namespacebindings:
                
                namespaceinfo=['','','']
                namespaceinfo[2]=translateMasks(str.lower(namespacespec[2]).split('+'))
                namespaceinfo[1] = XK.string_to_keysym(namespacespec[1])
                namespaceinfo[0]=namespacespec[0]    
                #Store namespace info in namespacebinding list
                namespacebindinglist.append(namespaceinfo)
                keybindings=namespacebindings.get(namespacespec)
                
                for keyspec in keybindings:
                    """
                    See keys.py format for more details 
                    Here we extract toggle command list from the keys file
                    and record the number of commands to toggle in commandlistlength
                    and store it into bindings if it is the count of tuples 
                    specifying command entries.If not then the tuple must be 
                    a command entry itself and not a list of commands as expected 
                    in which case we set commandlistlength to 1 and proceed.
                    """
                    newkeyspec=[]
                    commandlistlength=len(keyspec[2])
                    if type(keyspec[2][0])==types.StringType:
                        commandlistlength=1
                    
                    newkeyspec.append(keyspec[0])
                    newkeyspec.append(keyspec[1])
                    newkeyspec.append(keyspec[2])
                    newkeyspec.append(commandlistlength)
                        #We use the last entry to specify which command in the toggle list to
                        #execute.This is cycled at every command.It is what enables us to remember
                        #the state of the toggle behavior
                    newkeyspec.append(0)
                    #Store namespace name that the current key binding is associated with
                    newkeyspec.append(namespaceinfo[0])
                    #Set Maskcodes for use with X.The second entry consists of modifiers
                    #in the form shift+control+mod1 etc.
                    #Similarly convert keystrings to symbolic form used by X.Thus
                    #we have successfully converted the user-friendly keybinding structure into a
                    #wm-friendly one
                  
                    newkeyspec[1]=translateMasks(str.lower(keyspec[1]).split('+'))
                    newkeyspec[0] = XK.string_to_keysym(keyspec[0])
                    keybindinglist.append(newkeyspec)
                    
            return (keybindinglist,namespacebindinglist,namespaceexitbinding)
        else:
            return ([],[],[])
    
if __name__=="__main__":
    print KeyConfig.GetKeyBindings()
    
      